﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Web;
using System.Web.Mvc;

namespace mForum.Web.Common.Infrastructure.AssetManager.Handlers
{
    using mForum.Core.Common;
    using mForum.Core.Infrastructure.IoC;
    using mForum.Core.Infrastructure;
    using mForum.Web.Common.Infrastructure;
    using mForum.Web.Common.Infrastructure.Cache;
    using mForum.Web.Common.Infrastructure.AssetManager;

    public abstract class AssetHandlerBase : IHttpHandler
    {
        private IFileWrapper _fileWrapper;
        private IHttpContextProvider _httpContextProvider;
        private ICache _cache;

        public const string fileLastModificationParamName = "d";
        public const string fileTypeParamName = "t";

        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            DoProcess(IoC.GetInstance<IFileWrapper>(), IoC.GetInstance<IHttpContextProvider>(), IoC.GetInstance<ICache>());
        }

        public void DoProcess(IFileWrapper fileWrapper, IHttpContextProvider httpContextProvider, ICache cache)
        {
            _fileWrapper = fileWrapper;
            _httpContextProvider = httpContextProvider;
            _cache = cache;

            string fileLastModificationDate = _httpContextProvider.Request.QueryString[fileLastModificationParamName];
            string assetCategory = _httpContextProvider.Request.QueryString[fileTypeParamName];

            Check.Argument.IsNotEmpty(assetCategory, "fileType");
            Check.Argument.IsNotEmpty(fileLastModificationDate, "fileLastModificationDate");

            string key = PostprocessingCacheHelper.CreatePostprocessingCacheKey(GetAssetType(), assetCategory);
            string responseContent = PostprocessingCacheHelper.GetContent(key, _cache);

            lock (PostprocessingCacheHelper.SyncRoot)
            {
                if (responseContent == null)
                {
                    List<AssetItem> files = PostprocessingCacheHelper.GetFilesList(GetAssetType(), assetCategory, _cache);

                    foreach(AssetItem file in files)
                    {
                        if (!IsFileAllowed(file.Url))
                            throw new SecurityException("File is not allowed for Handler");
                    }

                    StringBuilder response = new StringBuilder();

                    foreach (AssetItem file in files)
                    {
                        string path = _httpContextProvider.Request.MapPath(TransformFilePath(file.Url));
                        ConcatFileToResponse(response, _fileWrapper.ReadAllText(path));
                    }

                    responseContent = response.ToString();
                    PostprocessingCacheHelper.SetContent(key, responseContent, _cache);
                }

                SetupResponse(_httpContextProvider, responseContent);

                _httpContextProvider.Response.Write(responseContent);
                _httpContextProvider.Response.Flush();
            }
        }

        protected abstract bool IsFileAllowed(string file);

        protected virtual string GetAssetType()
        {
            return "";
        }

        protected virtual string TransformFilePath(string file)
        {
            return file;
        }

        protected virtual void ConcatFileToResponse(StringBuilder response, string fileContent)
        {
            response.Append(fileContent);
            response.AppendLine();
        }

        protected virtual void SetupResponse(IHttpContextProvider context, string responseContent)
        {
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetExpires(DateTime.Now.AddMonths(1));
        }
    }
}
